#ifndef __PROCESS_POOL_HPP__
#define  __PROCESS_POOL_HPP__

#include<iostream>
#include<stdio.h>
#include<string>
#include<vector>
#include<cstdlib>
#include<functional>//仿函数
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<ctime>

#include"Test.hpp"
#include <bits/basic_string.h>

//创建子进程、管道的个数
const int gdefault_process_num = 5;

//回调函数 - lambda
//相当于： typedef std::functiion<void(int fd)> callback_t;
using callback_t = std::function<void(int fd)>;

//先描述再组织
class Channel
{
public:
    //默认构造
    Channel()
    {

    }
    //带参数的构造
    Channel(int fd , const std::string& name , pid_t id):_wfd(fd),_name(name),_sub_target(id)
    {

    }
    //打印,为了方便观察数据的情况
    void DebugPrint()
    {
        printf("channel name:%s , wfd:%d , target pis: %d\n" ,_name.c_str(), _wfd, _sub_target);
    }
    //析构
    ~Channel(){}
    //提供get 函数
    int Fd(){ return _wfd;}
    std::string Name(){return _name;}
    pid_t Target()
    {
        return _sub_target;
    }

private:
    int _wfd;//文件描述符
    std:: string _name;//进程名称
    pid_t _sub_target;//子进程的pid
};

//初始化进程池
bool InitProcessPool(std::vector<Channel> & channels , callback_t cd)
{
    //1、首先是创建管道, 使用系统调用 pipe
    // 所要包含的头文件：#include <unistd.h>   使用：int pipe(int pipefd[2]);
    //返回值，返回0表示成功，小于0表示失败
    int pipefd[2] = {0};
    int n = pipe(pipefd);
    if(n<0) return false;

    for(int i = 0;i<gdefault_process_num;i++)
    {
            //2、创建子进程
    //父进程需要循环创建,创建子进程需要用到系统调用：fork
    //#include <unistd.h>  pid_t fork(void); ,返回值小于0就是创建失败，为0为子进程，非0为父进程
    pid_t id = fork();
    if(id < 0) return false;
    if(id == 0)//子进程
    {
        //子进程从管道读取数据
        //3、关闭子进程不会使用的rw端，此处子进程是读，所以关闭写端
        close(pipefd[1]);

        //子进程做事

        //子进程走到此处退出即可
        exit(0);
    }
    //父进程写，所以需要关闭父进程的读端
    close(pipefd[0]);
    //将管道放入数组中进行管理
    std::string name = "channel-"+ std::to_string(i);
    //此处可以使用push_back 也可以使用emplace_back
    // channels.push_back({pipefd[1] , name , id});
    channels.emplace_back(pipefd[1], name , id);
    }
    return true;
}

int main()
{
    //父进程
    //组织-管理所有的信道
    std::vector<Channel> channels;
    //1、创建进程池，让进程池进入自己的工作流之中，父进程需要得到channels 来进行记录、管理信道
    InitProcessPool(channels , [](int fd){
        while(true)
        {
            int code = 0;
            std::cout<<"子进程阻塞："<<getpid()<<std::endl;
            //子进程从管道中读取数据，当写端开启的时候，如果管道中没有数据，那么子进程就会一直等待
            ssize_t n = read(fd , &code, sizeof(code));//n 是读取的数据个数
            if(n>0)
            {
                std::cout<<"子进程被唤醒："<<getpid()<<std::endl;
            }
        }
    });

    //2、控制唤醒指定的一个子进程，让该子进程完成自定的任务
    //2.1、负载均衡：轮询or 随机值 or 利用变量记录加载的次数，每次选择最小的那一个进程来执行任务
    int index = 0;
    while(true)
    {
        int who = 0;
        index++;
        index %= channels.size();//模等信道的个数
        int x = 1;//假设这是


    }

}

#endif